package com.cyj.dream.admin.controller.admin.system;

import com.cyj.dream.admin.model.system.SysPermission;
import com.cyj.dream.admin.service.system.SysPermissionService;
import com.cyj.dream.core.aspect.annotation.ResponseResult;
import com.cyj.dream.core.aspect.annotation.log.LogRecord;
import com.cyj.dream.core.aspect.enums.OperatorType;
import com.cyj.dream.core.constant.Constant;
import com.cyj.dream.core.util.IsEmptyUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.*;

/**
 * @Description: 系统权限控制器
 * @BelongsProject: fckj-restaurant
 * @BelongsPackage: com.fckj.fckjrestaurant.controller.admin.systems
 * @Author: ChenYongJia
 * @CreateTime: 2021-05-18 11:16
 * @Email: chen87647213@163.com
 * @Version: 1.0
 */
@Slf4j
@RestController
@ResponseResult
@Api(value = "permission", tags = "系统权限模块")
@RequestMapping(value = "/pc/permission", name = "系统权限模块")
public class SysPermissionController {

    /**
     * springmvc在启动时候将所有贴有请求映射标签：RequestMapper方法收集起来封装到该对象中
     * SpringMVC所有控制器中的请求映射集合
     */
    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Autowired
    private SysPermissionService sysPermissionService;

    /**
     * 更新系统权限信息
     *
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @date 2021/5/18 11:19
     * @author ChenYongJia
     * @version 1.0
     */
    @ApiOperation(value = "更新项目管理系统权限信息", httpMethod = "POST")
    @LogRecord(title = "更新项目管理系统权限信息", operatetype = OperatorType.INSERT)
    @RequestMapping(value = "/updatePermission", name = "更新项目管理系统权限信息", method = RequestMethod.POST)
    public Map<String, Object> updatePermission() {
        log.info("进入更新项目管理系统权限信息方法...");

        Map<String, Object> map = new HashMap<>(Constant.INITIAL_CAPACITY);
        if (this.updateSysPermission()) {
            map.put("info", "成功更新项目管理系统权限信息！");
        } else {
            map.put("error", "更新项目管理系统权限信息失败！");
        }

        return map;
    }

    /**
     * 收集系统中所有权限数据更新到数据库
     *
     * @return boolean
     * @date 2021-5-18 14:56:58
     * @author ChenYongJia
     * @version 1.0
     */
    public boolean updateSysPermission() {
        // 查询出数据库中现有的所有权限数据集合
        List<String> ownList = sysPermissionService.queryAll();
        // SpringMVC所有控制器中的请求映射集合
        Map<RequestMappingInfo, HandlerMethod> requestMap = handlerMapping.getHandlerMethods();
        // 获取所有controller中所有带有@RequestMapper注解的方法
        Collection<HandlerMethod> handlerMethods = requestMap.values();
        if (IsEmptyUtils.isEmpty(handlerMethods)) {
            // 成功更新0条数据
            return true;
        }

        // 收集到的待新增的权限集合
        List<SysPermission> pList = new ArrayList<>();
        // 待添加的权限对象
        SysPermission permission;
        // 遍历所有带有@RequestMapper注解的方法
        for (HandlerMethod method : handlerMethods) {
            // 从控制器映射方法上取出@RequestMapper注解对象
            RequestMapping anno = method.getMethodAnnotation(RequestMapping.class);
            // @RequestMapper注解有没有name备注是作为一个权限的标志，@RequestMapper注解写了name属性才做权限收集：所以@RequestMapper注解有没有name备注是作为一个权限的标志
            if (!"".equals(anno.name())) {
                // 带有@RequestMapper注解的方法所在控制器类上的RequestMapping注解对象
                RequestMapping namespaceMapping = method.getBeanType().getAnnotation(RequestMapping.class);
                // 得到RequestMapping注解的value值,即命名空间,即模块
                String namespace = namespaceMapping.value()[0];
                // 得到权限 ,例如：user:delete
                String permissionValue = (namespace + ":" + anno.value()[0]).replace("/", "");
                // 用户模块的删除权限
                if (ownList.contains(permissionValue)) {
                    // 如果数据库已经存储有这个注解权限,则忽略不收集
                    continue;
                }
                if (pList.contains(permissionValue)) {
                    // 如果已经收集到该权限,则忽略不再重复收集
                    continue;
                }
                // 构造权限对象,三个参数:权限,模块说明,权限说明,把权限控制注解@Permission解析为权限控制对象SysPermission,方便插入数据库权限表
                permission = new SysPermission(permissionValue, namespaceMapping.name(), anno.name());
                // 把数据库没有存储的,收集容器中也没有收集到的的权限加入收集容器中.
                pList.add(permission);
            }
        }

        if (!IsEmptyUtils.isEmpty(pList.size())) {
            return sysPermissionService.batchInsert(pList);
        } else {
            return false;
        }
    }

}
